/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.object;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import net.worlds.WorldsException;
import net.worlds.Main;
import net.worlds.MultiTraceResult;
import net.worlds.TraceResult;
import org.jbox2d.common.Vec2D;
import org.jbox2d.dynamics.Body;


public class Explosion extends GameObject implements Steppable, Prop{
    private ArrayList<Body> bodies = new ArrayList<Body>(64);
    private final Color[] possibleColors = new Color[]{Color.red, Color.orange, new Color(150, 0, 0), new Color(220, 130, 30)};
    private Color color;
    private int radius = 1;
    private int maxRadius;
    private Vec2D screenPos;
    private long deathTime;
    private long animTime;
    public int explosionID = (int) (Math.random() * Integer.MAX_VALUE);
    public Explosion() throws WorldsException
    {
        super("Explosion");
        //x_;
    }
    @Override
    public void draw(Graphics g) throws WorldsException
    {
        if(maxRadius > 0)
        {
            double t = 1 - ((double)radius/(maxRadius));
            t = Math.max(Math.min(t, 1), 0);
            g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), (int) (t * 255)));
            g.fillOval((int) screenPos.x - radius, (int) screenPos.y - radius, radius * 2, radius * 2);
            if(System.currentTimeMillis() - animTime > 1 && radius < maxRadius)
            {
                animTime = System.currentTimeMillis();
                radius += 5;
            }
        }
        /*for(Body b : bodies)
        {
            g.setColor(Color.red);
            Vec2D pos = new Vec2D(b.getPosition()).worldToScreen(Main.getView());
            System.err.println(pos);
            g.fillOval((int) pos.getX() - 8, (int) pos.getY() - 8, 16, 16);
        }*/
    }
    @Override
    public void step() throws WorldsException
    {
        if(bodies.isEmpty() && deathTime == 0)
            deathTime = System.currentTimeMillis();
        if(radius >= maxRadius)
            setProp("Parent",  null, true);
        if(Main.noView && System.currentTimeMillis() - animTime > 1 && radius < maxRadius)
        {
            animTime = System.currentTimeMillis();
            radius += 5;
        }
    }
    @Override
    public void addToWorld() throws WorldsException
    {
        super.addToWorld();
        Runnable r = new Runnable()
        {
            public void run()
            {
                try {
                    explode();
                } catch (WorldsException ex) {
                    ex.printStackTrace();
                }
            }
        };
        Main.runInMainThread(r);
    }
    private void explode() throws WorldsException
    {
        final Vec2D position = getVec2DProp("Position");
        if(!Main.isClient())
        {
            worldLocked = true;
            for(float a = 0; a < 360; a += 30)
            {
                Vec2D unit = new Vec2D(Math.toRadians(a));
                MultiTraceResult multi = world.getMultiTrace(position, unit, null, getFloatProp("Radius"));
                for(TraceResult trace : multi.results)
                {
                    Part p = trace.part;
                    float distanceRatio = trace.distanceVec.length() / (float)getFloatProp("Radius");
                    p.getBody().applyForce(unit.mul((float) getFloatProp("Force") * distanceRatio * p.getBody().getMass()/15f), trace.end);
                }


            }
            final List<GameObject> characters = world.getObjectsByType(Character.class);
            synchronized(characters)
            {
                Main.addTempTask(new Runnable()
                {

                    public void run() {
                        for(GameObject obj : characters)
                        {
                            try {
                                Character c = (Character) obj;
                                if (c.hasChild("Body") && c.getChild("Body") instanceof Part) {
                                    Vec2D pos = c.getChild("Body").getVec2DProp("Position");
                                    double distance = new Vec2D(pos.x - position.x, pos.y - position.y).length();
                                    if (distance < 2 * getFloatProp("Radius")) {
                                        double amount = 1 - (distance) / (4 * getFloatProp("Radius"));
                                        if (amount < 0) {
                                            amount = 0;
                                        } else if (amount > 1) {
                                            amount = 1;
                                        }
                                        double v = c.getIntProp("MaximumHealth") * amount;
                                        if (v > c.getIntProp("Health")) {
                                            v = c.getIntProp("Health");
                                        }
                                        c.setProp("Health", (int) (c.getIntProp("Health") - v), true);
                                    }
                                }
                            } catch (WorldsException ex) {
                                ex.printStackTrace();
                             }
                        }
                    }
                });
            }
            Main.processTempTasks();
            List<GameObject> joints = world.getJoints();
            synchronized(joints)
            {
                for(GameObject obj : joints)
                {
                    Joint j = (Joint) obj;
                    Vec2D pos = j.getVec2DProp("Anchor");
                    double distance = new Vec2D(pos.x - position.x, pos.y - position.y).length();
                    if(distance < getFloatProp("Radius"))
                    {
                        j.setProp("Parent", null, true);
                    }

                }
            }
        }
        worldLocked = false;
        if(!Main.noView)
            screenPos = position.worldToScreen(Main.getView());
        if(!Main.noView)
            maxRadius = (int) (getFloatProp("Radius") * Main.getView().scaleFactor);
        else
            maxRadius = (int) (getFloatProp("Radius") * 8);
        int r = (int) Math.round(Math.random() * (possibleColors.length - 1));
        color = possibleColors[r];
    }
}
